import pytest
import responses
import requests
from urllib.parse import urlencode
import allure
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
import os
import datetime

# 模拟API成功响应
MOCK_SUCCESS_RESPONSE = '{"Response":{"InstanceOperationLimitSet":[{"Operation":"INSTANCE_DEGRADE","InstanceId":"ins-12345678","CurrentCount":0,"LimitCount":5}],"RequestId":"req-123"}}'

# 模拟API错误响应（缺少必填参数）
MOCK_ERROR_RESPONSE = '{"Error":{"Code":"MissingParameter","Message":"缺少必填参数InstanceId"}}'

# 邮件配置
MAIL_CONFIG = {
    "smtp_server": "smtp.qq.com",
    "smtp_port": 465,
    "sender_email": "2811306659@qq.com",
    "sender_password": "zepgneuruyuadffe",  # QQ邮箱授权码
    "receiver_email": "2811306659@qq.com"
}

# Allure报告配置（修改为绝对路径）
ALLURE_RESULTS_DIR = r"D:\Allure\Allure-results"  # 原始结果存储目录
ALLURE_REPORT_DIR = r"D:\Allure\Allure-results"  # 生成后的HTML报告目录


class TestCvmInstanceLimit:

    @allure.feature("CVM实例限制测试")
    @responses.activate
    def test_valid_request(self):
        """测试正常查询请求"""
        params = {
            "Action": "DescribeInstancesOperationLimit",
            "InstanceIds.0": "ins-12345678",
            "Operation": "INSTANCE_DEGRADE",
            "Version": "2017-03-12",
            "Region": "ap-guangzhou"
        }
        expected_url = f"https://cvm.tencentcloudapi.com/?{urlencode(params)}"

        responses.add(responses.GET, expected_url, body=MOCK_SUCCESS_RESPONSE, status=200)

        resp = requests.get(expected_url)
        resp.raise_for_status()

        data = resp.json()
        assert data["Response"]["InstanceOperationLimitSet"][0]["LimitCount"] == 5

    @allure.feature("CVM实例限制测试")
    @responses.activate
    def test_missing_required_params(self):
        """测试缺少必填参数"""
        params = {
            "Action": "DescribeInstancesOperationLimit",
            "Operation": "INSTANCE_DEGRADE",
            "Version": "2017-03-12",
            "Region": "ap-guangzhou"
        }
        expected_url = f"https://cvm.tencentcloudapi.com/?{urlencode(params)}"

        responses.add(responses.GET, expected_url, body=MOCK_ERROR_RESPONSE, status=400)

        # 发送请求并触发异常
        resp = requests.get(expected_url)
        try:
            resp.raise_for_status()
        except requests.HTTPError as e:
            # 解析响应体中的错误信息
            error_data = e.response.json()["Error"]
            assert error_data["Code"] == "MissingParameter"
            assert "InstanceId" in error_data["Message"]
        else:
            pytest.fail("Expected HTTPError not raised")


# Pytest钩子函数：测试结束后生成报告并发送邮件
def pytest_sessionfinish(session, exitstatus):
    # 确保Allure结果目录存在
    os.makedirs(ALLURE_RESULTS_DIR, exist_ok=True)

    # 生成Allure报告
    generate_allure_report()
    # 发送邮件
    send_test_report()


# 生成Allure测试报告
def generate_allure_report():
    # 执行测试并收集结果（需要重新导入测试类）
    import sys
    from pathlib import Path
    sys.path.append(str(Path(__file__).parent))

    # 使用绝对路径配置Allure结果目录
    pytest.main([
        "--alluredir", ALLURE_RESULTS_DIR,
        "--clean-alluredir",
        "-s"
    ])

    # 生成HTML报告
    os.system(f"allure generate {ALLURE_RESULTS_DIR} -o {ALLURE_REPORT_DIR} --clean")


# 发送测试报告邮件
def send_test_report():
    # 创建邮件主体
    msg = MIMEMultipart()
    msg["From"] = MAIL_CONFIG["sender_email"]
    msg["To"] = MAIL_CONFIG["receiver_email"]
    msg["Subject"] = f"腾讯云API自动化测试报告 - {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"

    # 添加HTML正文
    html_content = f"""
    <html>
    <body>
        <h3>腾讯云API自动化测试报告</h3>
        <p>测试执行时间：{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
        <p>测试结果概要：</p>
        <ul>
            <li>总用例数：{len(pytest.session.testscollected)}</li>
            <li>通过用例：{pytest.session.passed}</li>
            <li>失败用例：{pytest.session.failed}</li>
            <li>跳过用例：{pytest.session.skipped}</li>
        </ul>
        <p>详细报告请查看附件：</p>
        <a href="cid:report">点击此处查看Allure报告</a>
    </body>
    </html>
    """
    msg.attach(MIMEText(html_content, "html"))

    # 添加附件
    report_path = os.path.join(ALLURE_REPORT_DIR, "index.html")
    if not os.path.exists(report_path):
        raise FileNotFoundError(f"测试报告文件不存在: {report_path}")

    with open(report_path, "rb") as f:
        part = MIMEApplication(f.read(), Name=os.path.basename(report_path))
        part.add_header("Content-ID", "<report>")
        part.add_header("Content-Disposition", f'attachment; filename="{os.path.basename(report_path)}"')
        msg.attach(part)

    # 发送邮件
    try:
        with smtplib.SMTP_SSL(MAIL_CONFIG["smtp_server"], MAIL_CONFIG["smtp_port"]) as server:
            server.login(MAIL_CONFIG["sender_email"], MAIL_CONFIG["sender_password"])
            server.sendmail(
                MAIL_CONFIG["sender_email"],
                MAIL_CONFIG["receiver_email"],
                msg.as_string()
            )
        print("\n📧 测试报告发送成功！")
    except Exception as e:
        print(f"\n❌ 发送邮件失败: {str(e)}")


# 运行测试
if __name__ == "__main__":
    pytest.main(["-s", "--alluredir", ALLURE_RESULTS_DIR])